package psoa.ruleml.parser;


import java.io.*;
import java.util.*;
import java.net.*;

import javax.xml.bind.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.validation.*;

import org.w3c.dom.DocumentType;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

//import com.sun.org.apache.xerces.internal.parsers.DOMParser;

import psoa.ruleml.AbstractSyntax.Atom;
import psoa.ruleml.AbstractSyntax.Atomic;
import psoa.ruleml.AbstractSyntax.Clause;
import psoa.ruleml.AbstractSyntax.Equal;
import psoa.ruleml.AbstractSyntax.Formula;
import psoa.ruleml.AbstractSyntax.Formula_External;
import psoa.ruleml.AbstractSyntax.Group;
import psoa.ruleml.AbstractSyntax.GroupElement;
import psoa.ruleml.AbstractSyntax.Head;
import psoa.ruleml.AbstractSyntax.Implies;
import psoa.ruleml.AbstractSyntax.Import;
import psoa.ruleml.AbstractSyntax.Profile;
import psoa.ruleml.AbstractSyntax.Psoa;
import psoa.ruleml.AbstractSyntax.Slot;
import psoa.ruleml.AbstractSyntax.Subclass;
import psoa.ruleml.AbstractSyntax.Symspace;
import psoa.ruleml.AbstractSyntax.Term;
import psoa.ruleml.AbstractSyntax.Tuple;
import psoa.ruleml.AbstractSyntax.Var;
import psoa.ruleml.parser.jaxb.*;
import psoa.ruleml.AbstractSyntax;


public class Parser {
	
	public Parser() throws java.lang.Exception {
		
		JAXBContext jc = JAXBContext.newInstance("psoa.ruleml.parser.jaxb");
		_unmarshaller = jc.createUnmarshaller();
		SchemaFactory schemaFactory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
		//absolute path
		//URL schemaURL = new File("./src/main/resources/PSOARule.xsd").toURI().toURL();
		 URL schemaURL = 
	            ClassLoader.
	            getSystemResource("PSOARule.xsd");
		//URL schemaURL = ClassLoader.getSystemClassLoader().getResource("PSOARule.xsd");
		if(schemaFactory != null){
			System.out.println("schemaFactory is not null "+ schemaURL);
			
		}
		
		long startTime = System.currentTimeMillis();

		//taking too much time to create new schema
		Schema schema = schemaFactory.newSchema(schemaURL);
		long endTime = System.currentTimeMillis();

		System.out.println("creating new schema That took " + (endTime - startTime) + " milliseconds");

		_unmarshaller.setSchema(schema);
		
		
		

	}
	
	 /** @param file to be parsed
     *   @param absSynFactory factory of abstract syntax objects
     *         to be used to create the parsed objects
     */
	public AbstractSyntax.Document
	parse(File file, AbstractSyntax absSynFactory)
	throws java.lang.Exception{
		
		try {
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			org.w3c.dom.Document d = db.parse(file);
			DocumentType dt = d.getDoctype();
			
			NamedNodeMap nnm = dt.getEntities();
			Node entity = nnm.item(0);
			System.out.println(entity);
			
			String wholedoc = dt.getInternalSubset();
			System.out.println(wholedoc);
			
			
			 NamedNodeMap entities = dt.getEntities();
             if (entities!=null) {
                 entity = entities.getNamedItem("instance");
                 if (entity != null) {
                     System.out.println("ENTITY book="+entity.getNodeValue());
                     Node child = entity.getFirstChild();
                     while (child != null) {
                         System.out.println("==>child: '"+child.getNodeName()+"' " + child.getNodeValue());
                         child = child.getNextSibling();
                     }

                 }
             }
             

			
			
			
			
			
			
			
			
			Document doc = (Document) _unmarshaller.unmarshal(file);
			Directive directive = doc.getDirective();
			Payload payload = doc.getPayload();
			
			if (directive != null){
			
				if (payload != null && directive.getImport() != null){//only import
				psoa.ruleml.parser.jaxb.Group topLevelGroup = payload
				.getGroup();
		return absSynFactory.createDocument(convertImport(directive.getImport(),
				absSynFactory), (Group) convert(topLevelGroup,
				absSynFactory));
				
			} 
			}			
			else {
			
				if (payload != null) {//no directive
				psoa.ruleml.parser.jaxb.Group topLevelGroup = payload
						.getGroup();
				return absSynFactory.createDocument(null, (Group) convert(
						topLevelGroup, absSynFactory));
			}
			}//end directive.getClass() null
				
				
				
				return absSynFactory.createDocument(null, null);


		}

		catch(javax.xml.bind.UnmarshalException ex){
			throw new java.lang.Exception("PSOA RULEML file cannot be read" + ex);
		}
	}
	
	/**
	 * @param import1
	 * @param absSynFactory
	 * @return
	 */	

private Iterable<Import> convertImport(
			List<psoa.ruleml.parser.jaxb.Import> import1,
			AbstractSyntax absSynFactory) {
		// TODO Auto-generated method stub
	LinkedList<AbstractSyntax.Import> results = new LinkedList<AbstractSyntax.Import>();
	for (psoa.ruleml.parser.jaxb.Import imp : import1){
		if (imp.getLocation() != null && imp.getProfile() != null){
			AbstractSyntax.Profile profile = convertProfile(imp.getProfile(),absSynFactory);
			results.add(absSynFactory.createImport(imp.getLocation(), profile));
		} else if (imp.getLocation() != null){
			results.add(absSynFactory.createImport(imp.getLocation(), null));
		}
	}
		return results;
	}

private Profile convertProfile(String profile, AbstractSyntax absSynFactory) {
	// TODO Auto-generated method stub
	if (!profile.isEmpty()){
		return absSynFactory.createProfile(profile);
	} else
		throw new Error("Bad instance of Profile");
}

/**********************************************************
 * 
 * @param topLevelGroup
 *            Group or nested Groups
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Groups
 * @return Group or nested Groups
 */

private AbstractSyntax.GroupElement convert(
		psoa.ruleml.parser.jaxb.Group topLevelGroup,
		AbstractSyntax absSynFactory) {

	LinkedList<AbstractSyntax.GroupElement> grpElements = new LinkedList<AbstractSyntax.GroupElement>();
	for (Groupelement grpelm : topLevelGroup.getGroupelement())
		grpElements.addLast(convert(grpelm, absSynFactory));

	return absSynFactory.createGroup(grpElements);
}

/***********************************************************
 * 
 * @param grpelm
 *            each fact or rule to be parsed
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Groupelement
 * @return Groupelement as fact or rule
 */

private GroupElement convert(Groupelement grpelm,
		AbstractSyntax absSynFactory) {

	if (grpelm.getForall() != null) {
		Iterable<AbstractSyntax.Var> vars = convertVars(grpelm.getForall()
				.getDeclare(), absSynFactory);

		return absSynFactory.createRule(vars, convert(grpelm.getForall(),
				absSynFactory));
	}

	if (grpelm.getImplies() != null) {
		AbstractSyntax.Clause clause = convert(grpelm.getImplies(),
				absSynFactory);

		return absSynFactory.createRule(null, clause);
	}

	if (grpelm.getEqual() != null) {
		AbstractSyntax.Equal equal = convert(grpelm.getEqual(),
				absSynFactory);
		AbstractSyntax.Clause clause = absSynFactory.createClause(equal);

		return absSynFactory.createRule(null, clause);
	}

	if (grpelm.getSubclass() != null) {
		AbstractSyntax.Subclass subclass = convert(grpelm.getSubclass(),
				absSynFactory);
		AbstractSyntax.Clause clause = absSynFactory.createClause(subclass);

		return absSynFactory.createRule(null, clause);
	}

	if (grpelm.getAtom() != null) {
		AbstractSyntax.Atom atom = convert(grpelm.getAtom(), absSynFactory);
		AbstractSyntax.Clause clause = absSynFactory.createClause(atom);

		return absSynFactory.createRule(null, clause);
	}

	if (grpelm.getGroup() != null) {
		AbstractSyntax.GroupElement gr = convert(grpelm.getGroup(),
				absSynFactory);
		AbstractSyntax.Group g = (Group) gr;

		return g;
	}

	throw new Error("Bad instance of Groupelement.");
}

/**
 * 
 * @param implies
 *            to be parsed as Implication
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Implication
 * @return Clause as Implication containing both Conditions and Conclusion
 *         or only Conclusion as an Atomic formula or Conjunction of Atomic
 *         formulas
 * 
 */
private Clause convert(psoa.ruleml.parser.jaxb.Implies implies,
		AbstractSyntax absSynFactory) {

	AbstractSyntax.Formula cond = convert(implies.getIf(), absSynFactory);
	LinkedList<AbstractSyntax.Head> heads = convert(implies.getThen(),
			absSynFactory);
	Implies impl = absSynFactory.createImplies(heads, cond);

	return absSynFactory.createClause(impl);
}

private LinkedList<Head> convert(Then then, AbstractSyntax absSynFactory) {

	Iterable<AbstractSyntax.Var> vars = null;
	LinkedList<AbstractSyntax.Head> heads = new LinkedList<AbstractSyntax.Head>();
	AbstractSyntax.Atomic atomic = null;

	if (then.getAtom() != null) {
		atomic = convert(then.getAtom(), absSynFactory);
		heads.add(absSynFactory.createHead(vars, atomic));

		return heads;
	} else if (then.getEqual() != null) {
		atomic = convert(then.getEqual(), absSynFactory);
		heads.add(absSynFactory.createHead(vars, atomic));

		return heads;
	} else if (then.getSubclass() != null) {
		atomic = convert(then.getSubclass(), absSynFactory);
		heads.add(absSynFactory.createHead(vars, atomic));

		return heads;
	} else if (then.getExists() != null) {
		vars = convertVars(then.getExists().getDeclare(), absSynFactory);
		atomic = convert(then.getExists().getFormula(), absSynFactory);
		heads.add(absSynFactory.createHead(vars, atomic));

		return heads;
	} else if (then.getAnd() != null) {
		java.util.List<FormulaAndThenType> formulae = then.getAnd()
				.getFormula();

		for (FormulaAndThenType form : formulae) {
			if (form.getAtom() != null) {
				atomic = convert(form.getAtom(), absSynFactory);
				heads.add(absSynFactory.createHead(vars, atomic));
				vars = null;
			} else if (form.getEqual() != null) {
				atomic = convert(form.getEqual(), absSynFactory);
				heads.add(absSynFactory.createHead(vars, atomic));
				vars = null;
			} else if (form.getSubclass() != null) {
				atomic = convert(form.getSubclass(), absSynFactory);
				heads.add(absSynFactory.createHead(vars, atomic));
				vars = null;
			} else if (form.getExists() != null) {
				vars = convertVars(form.getExists().getDeclare(),
						absSynFactory);
				atomic = convert(form.getExists().getFormula(),
						absSynFactory);
				heads.add(absSynFactory.createHead(vars, atomic));
				vars = null;
			} else
				throw new Error("Bad instance of FormulaAndThenType");
		}

	} else
		throw new Error("bad instance of Then");

	return heads;
}

/**
 * 
 * @param formula
 *            to be parsed as Atomic formulas as Atom, Equality or Subclass
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Atomic formula
 * @return Atomic formulas as Atom, Equal or Subclass
 */
private Atomic convert(FormulaExistsThenType formula,
		AbstractSyntax absSynFactory) {

	AbstractSyntax.Atomic atomic;

	if (formula.getAtom() != null) {
		atomic = convert(formula.getAtom(), absSynFactory);
	} else if (formula.getEqual() != null) {
		atomic = convert(formula.getEqual(), absSynFactory);
	} else if (formula.getSubclass() != null) {
		atomic = convert(formula.getSubclass(), absSynFactory);
	} else
		throw new Error("Bad instance of FormulaExistsThenType");

	return atomic;
}

/**
 * 
 * @param con
 *            to be parsed as Condition formulas
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Condition formulas
 * @return Formula as Atom, Equal, Subclass, Conjunction
 *         formulas,disjunction formulas existential formulas, external
 *         formulas
 */
private Formula convert(If con, AbstractSyntax absSynFactory) {

	AbstractSyntax.Formula body;

	if (con.getAtom() != null) {
		body = convert(con.getAtom(), absSynFactory);
		return body;
	} else if (con.getEqual() != null) {
		body = convert(con.getEqual(), absSynFactory);
		return body;
	} else if (con.getSubclass() != null) {
		body = convert(con.getSubclass(), absSynFactory);
		return body;
	} else if (con.getAnd() != null) {
		body = convert(con.getAnd(), absSynFactory);
		return body;
	} else if (con.getOr() != null) {
		body = convert(con.getOr(), absSynFactory);
		return body;
	} else if (con.getExists() != null) {
		body = convert(con.getExists(), absSynFactory);
		return body;
	} else if (con.getExternal() != null) {
		body = convert(con.getExternal(), absSynFactory);
		return body;
	} else
		throw new Error("Bad instance of If");
}

/**
 * 
 * @param external
 *            to be parsed as external formula
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create external formulas
 * @return Formula_External as external formula
 */
private Formula_External convert(ExternalFORMULAType external,
		AbstractSyntax absSynFactory) {

	return absSynFactory.createFormula_External(convert(external
			.getContent().getAtom(), absSynFactory));
}

/**
 * 
 * @param exists
 *            to be parsed as existential formula
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Exist formula
 * @return Formula as formula with existentially quantified variables
 */
private Formula convert(Exists exists, AbstractSyntax absSynFactory) {

	Iterable<AbstractSyntax.Var> vars = convertVars(exists.getDeclare(),
			absSynFactory);
	AbstractSyntax.Formula form = convert(exists.getFormula(),
			absSynFactory);

	return absSynFactory.createFormula_Exists(vars, form);
}

/**
 * 
 * @param formula
 *            to be parsed as any or all of conjunction, disjunction,
 *            existential, external or atomic formula
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create formulas
 * @return Formula as Atomic, External, Existentially quantified formula, or
 *         conjunction, disjunction of those formulas
 */
private Formula convert(psoa.ruleml.parser.jaxb.Formula formula,
		AbstractSyntax absSynFactory) {

	if (formula.getAnd() != null) {
		return convert(formula.getAnd(), absSynFactory);
	} else if (formula.getOr() != null) {
		return convert(formula.getOr(), absSynFactory);
	} else if (formula.getExists() != null) {
		return convert(formula.getExists(), absSynFactory);
	} else if (formula.getExternal() != null) {
		return convert(formula.getExternal(), absSynFactory);
	} else if (formula.getAtom() != null) {
		return convert(formula.getAtom(), absSynFactory);
	} else if (formula.getEqual() != null) {
		return convert(formula.getEqual(), absSynFactory);
	} else if (formula.getSubclass() != null) {
		return convert(formula.getSubclass(), absSynFactory);
	} else
		throw new Error("Bad instance of Formula");

}

/**
 * 
 * @param or
 *            to be parsed as disjunction of formulas
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create disjunction formulas
 * @return Formula as Disjunction of formulas
 */
private Formula convert(Or or, AbstractSyntax absSynFactory) {

	LinkedList<AbstractSyntax.Formula> orArgs = new LinkedList<AbstractSyntax.Formula>();

	for (psoa.ruleml.parser.jaxb.Formula form : or.getFormula()) {
		if (form.getAnd() != null) {
			orArgs.addLast(convert(form.getAnd(), absSynFactory));
		} else if (form.getOr() != null) {
			orArgs.addLast(convert(form.getOr(), absSynFactory));
		} else if (form.getEqual() != null) {
			orArgs.addLast(convert(form.getEqual(), absSynFactory));
		} else if (form.getAtom() != null) {
			orArgs.addLast(convert(form.getAtom(), absSynFactory));
		} else if (form.getSubclass() != null) {
			orArgs.addLast(convert(form.getSubclass(), absSynFactory));
		} else if (form.getExists() != null) {
			orArgs.addLast(convert(form.getExists(), absSynFactory));
		} else if (form.getExternal() != null) {
			orArgs.addLast(convert(form.getExternal(), absSynFactory));
		} else
			throw new Error("Bad instance of Or");
	}

	return absSynFactory.createFormula_Or(orArgs);
}

/**
 * 
 * @param and
 *            to be parsed as Conjunction of formulas
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create disjunction formulas
 * @return Formulas as Conjunction or formulas
 */
private Formula convert(And and, AbstractSyntax absSynFactory) {

	LinkedList<AbstractSyntax.Formula> andArgs = new LinkedList<AbstractSyntax.Formula>();

	for (psoa.ruleml.parser.jaxb.Formula form : and.getFormula()) {
		if (form.getAnd() != null) {
			andArgs.addLast(convert(form.getAnd(), absSynFactory));
		} else if (form.getOr() != null) {
			andArgs.addLast(convert(form.getOr(), absSynFactory));
		} else if (form.getAtom() != null) {
			andArgs.addLast(convert(form.getAtom(), absSynFactory));
		} else if (form.getEqual() != null) {
			andArgs.addLast(convert(form.getEqual(), absSynFactory));
		} else if (form.getSubclass() != null) {
			andArgs.addLast(convert(form.getSubclass(), absSynFactory));
		} else if (form.getExists() != null) {
			andArgs.addLast(convert(form.getExists(), absSynFactory));
		} else if (form.getExternal() != null) {
			andArgs.addLast(convert(form.getExternal(), absSynFactory));
		} else
			throw new Error("Bad instance of and of Formula");
	}

	return absSynFactory.createFormula_And(andArgs);
}

/**
 * 
 * @param forall
 *            to be parsed as Universally quantified formulas
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create unversally quantified formulas
 * @return Clause as formula with the unviersally quantified variables
 */
private Clause convert(Forall forall, AbstractSyntax absSynFactory) {

	Forall.Formula form = forall.getFormula();
	AbstractSyntax.Atomic atomic = null;

	if (form.getEqual() != null) {
		AbstractSyntax.Equal equal = convert(form.getEqual(), absSynFactory);

		return absSynFactory.createClause(equal);
	} else if (form.getSubclass() != null) {
		AbstractSyntax.Subclass subclass = convert(form.getSubclass(),
				absSynFactory);

		return absSynFactory.createClause(subclass);
	} else if (form.getAtom() != null) {
		AbstractSyntax.Atom atom = convert(form.getAtom(), absSynFactory);

		return absSynFactory.createClause(atom);
	} else if (form.getImplies() != null) {
		AbstractSyntax.Clause clause = convert(form.getImplies(),
				absSynFactory);
		AbstractSyntax.Formula cond = convert(form.getImplies().getIf(),
				absSynFactory);
		LinkedList<AbstractSyntax.Head> heads = convert(form.getImplies()
				.getThen(), absSynFactory);
		Implies impl = absSynFactory.createImplies(heads, cond);

		return absSynFactory.createClause(impl);
	}

	return absSynFactory.createClause(atomic);
}

/**
 * 
 * @param atom
 *            to be parsed as psoa Atom
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Atom
 * @return Atom as a PSOA term composed of membership with optional tuples
 *         and slots
 */
private Atom convert(psoa.ruleml.parser.jaxb.Atom atom,
		AbstractSyntax absSynFactory) {

	if (atom.getMember() != null && atom.getTuple() != null
			&& atom.getSlot() != null)

		return absSynFactory.createAtom(convert(atom.getMember(), atom
				.getTuple(), atom.getSlot(), absSynFactory));
	if (atom.getMember() != null && atom.getTuple() != null)

		return absSynFactory.createAtom(convert(atom.getMember(), atom
				.getTuple(), absSynFactory));
	if (atom.getMember() != null && atom.getSlot() != null)

		return absSynFactory.createAtom(convert(atom.getMember(), atom
				.getSlot(), absSynFactory));

	return absSynFactory
			.createAtom(convert(atom.getMember(), absSynFactory));
}

/**
 * 
 * @param member
 *            to be parsed as membership with Object ID as instance of a
 *            class
 * @param tuple
 *            to be parsed as positional tuple terms
 * @param slot
 *            to be parsed as name, value pairs
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create a psoa term with membership including
 *            tuples and slots
 * @return Psoa term containing membership, tuples and slots altogether
 */
private Psoa convert(Member member, psoa.ruleml.parser.jaxb.Tuple tuple,
		List<SlotPSOAType> slot, AbstractSyntax absSynFactory) {

	Instance instance = member.getInstance();
	assert instance != null;
	AbstractSyntax.Term inst;

	if (instance.getConst() != null) {
		inst = convert(instance.getConst(), absSynFactory);
	} else if (instance.getVar() != null) {
		inst = convert(instance.getVar(), absSynFactory);
	} else if (instance.getExpr() != null) {
		inst = convert(instance.getExpr(), absSynFactory);
	} else if (instance.getExternal() != null) {
		inst = convert(instance.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Instance");

	psoa.ruleml.parser.jaxb.Class className = member.getClazz();
	assert className != null;
	AbstractSyntax.Term cls;

	if (className.getConst() != null) {
		cls = convert(className.getConst(), absSynFactory);
	} else if (className.getVar() != null) {
		cls = convert(className.getVar(), absSynFactory);
	} else if (className.getExpr() != null) {
		cls = convert(className.getExpr(), absSynFactory);
	} else if (className.getExternal() != null) {
		cls = convert(className.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Class");

	Iterable<Tuple> tupleTemp = convert(tuple, absSynFactory);
	Iterable<Slot> slotTemp = convert(slot, absSynFactory);

	return absSynFactory.createPsoa(inst, cls, tupleTemp, slotTemp);
}

/**
 * 
 * @param member
 *            to be parsed as membership with Object ID as instance of a
 *            class
 * @param slot
 *            to be parsed as name, value pairs
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create a psoa term with membership including
 *            slots
 * @return Psoa term containing membership and slots
 */
private Psoa convert(Member member, List<SlotPSOAType> slot,
		AbstractSyntax absSynFactory) {

	Instance instance = member.getInstance();
	assert instance != null;
	AbstractSyntax.Term inst;

	if (instance.getConst() != null) {
		inst = convert(instance.getConst(), absSynFactory);
	} else if (instance.getVar() != null) {
		inst = convert(instance.getVar(), absSynFactory);
	} else if (instance.getExpr() != null) {
		inst = convert(instance.getExpr(), absSynFactory);
	} else if (instance.getExternal() != null) {
		inst = convert(instance.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Instance");

	psoa.ruleml.parser.jaxb.Class className = member.getClazz();
	assert className != null;
	AbstractSyntax.Term cls;

	if (className.getConst() != null) {
		cls = convert(className.getConst(), absSynFactory);
	} else if (className.getVar() != null) {
		cls = convert(className.getVar(), absSynFactory);
	} else if (className.getExpr() != null) {
		cls = convert(className.getExpr(), absSynFactory);
	} else if (className.getExternal() != null) {
		cls = convert(className.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Class");

	Iterable<Slot> slotTemp = convert(slot, absSynFactory);

	return absSynFactory.createPsoa(inst, cls, null, slotTemp);
}

/**
 * 
 * @param slot
 *            to be parsed as name, value pairs
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create sequence of slots
 * @return sequence of Slots as name, value pairs
 */
private List<Slot> convert(List<SlotPSOAType> slot,
		AbstractSyntax absSynFactory) {

	LinkedList<AbstractSyntax.Slot> result = new LinkedList<AbstractSyntax.Slot>();
	AbstractSyntax.Term name = null;
	AbstractSyntax.Term value = null;

	for (SlotPSOAType sl : slot) {
		if (sl.getContent().get(0) instanceof psoa.ruleml.parser.jaxb.Var) {
			psoa.ruleml.parser.jaxb.Var tempName = (psoa.ruleml.parser.jaxb.Var) sl
					.getContent().get(0);
			name = convert(tempName, absSynFactory);
		} else if (sl.getContent().get(0) instanceof psoa.ruleml.parser.jaxb.Const) {
			psoa.ruleml.parser.jaxb.Const tempName = (psoa.ruleml.parser.jaxb.Const) sl
					.getContent().get(0);
			name = convert(tempName, absSynFactory);
		} else if (sl.getContent().get(0) instanceof psoa.ruleml.parser.jaxb.Expr) {
			psoa.ruleml.parser.jaxb.Expr tempName = (psoa.ruleml.parser.jaxb.Expr) sl
					.getContent().get(0);
			name = convert(tempName, absSynFactory);
		} else if (sl.getContent().get(0) instanceof psoa.ruleml.parser.jaxb.ExternalTERMType) {
			psoa.ruleml.parser.jaxb.ExternalTERMType tempName = (psoa.ruleml.parser.jaxb.ExternalTERMType) sl
					.getContent().get(0);
			name = convert(tempName, absSynFactory);
		}

		if (sl.getContent().get(1) instanceof psoa.ruleml.parser.jaxb.Var) {
			psoa.ruleml.parser.jaxb.Var tempValue = (psoa.ruleml.parser.jaxb.Var) sl
					.getContent().get(1);
			value = convert(tempValue, absSynFactory);
		} else if (sl.getContent().get(1) instanceof psoa.ruleml.parser.jaxb.Const) {
			psoa.ruleml.parser.jaxb.Const tempValue = (psoa.ruleml.parser.jaxb.Const) sl
					.getContent().get(1);
			value = convert(tempValue, absSynFactory);
		} else if (sl.getContent().get(1) instanceof psoa.ruleml.parser.jaxb.Expr) {
			psoa.ruleml.parser.jaxb.Expr tempValue = (psoa.ruleml.parser.jaxb.Expr) sl
					.getContent().get(1);
			value = convert(tempValue, absSynFactory);
		} else if (sl.getContent().get(1) instanceof psoa.ruleml.parser.jaxb.ExternalTERMType) {
			psoa.ruleml.parser.jaxb.ExternalTERMType tempValue = (psoa.ruleml.parser.jaxb.ExternalTERMType) sl
					.getContent().get(1);
			value = convert(tempValue, absSynFactory);
		}

		result.add(absSynFactory.createSlot(name, value));
	}

	return result;
}

/**
 * 
 * @param member
 *            to be parsed as membership with Object ID as instance of a
 *            class
 * @param tuple
 *            to be parsed as positional tuple terms
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create a psoa term with membership including
 *            tuples
 * @return Psoa term containing membership and tuples
 */
private Psoa convert(Member member, psoa.ruleml.parser.jaxb.Tuple tuple,
		AbstractSyntax absSynFactory) {

	Instance instance = member.getInstance();
	assert instance != null;
	AbstractSyntax.Term inst;

	if (instance.getConst() != null) {
		inst = convert(instance.getConst(), absSynFactory);
	} else if (instance.getVar() != null) {
		inst = convert(instance.getVar(), absSynFactory);
	} else if (instance.getExpr() != null) {
		inst = convert(instance.getExpr(), absSynFactory);
	} else if (instance.getExternal() != null) {
		inst = convert(instance.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Instance");

	psoa.ruleml.parser.jaxb.Class className = member.getClazz();
	assert className != null;
	AbstractSyntax.Term cls;

	if (className.getConst() != null) {
		cls = convert(className.getConst(), absSynFactory);
	} else if (className.getVar() != null) {
		cls = convert(className.getVar(), absSynFactory);
	} else if (className.getExpr() != null) {
		cls = convert(className.getExpr(), absSynFactory);
	} else if (className.getExternal() != null) {
		cls = convert(className.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Class");

	Iterable<Tuple> tupleTemp = convert(tuple, absSynFactory);

	return absSynFactory.createPsoa(inst, cls, tupleTemp, null);
}

/**
 * 
 * @param tuple
 *            to parsed as tuples or positional arguments
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create positional terms as arguments of a
 *            psoa term
 * @return sequence of Tuples as positional terms
 */
private Iterable<Tuple> convert(psoa.ruleml.parser.jaxb.Tuple tuple,
		AbstractSyntax absSynFactory) {

	assert tuple.getOrdered().equals("yes");
	LinkedList<AbstractSyntax.Term> result = new LinkedList<AbstractSyntax.Term>();

	for (java.lang.Object obj : tuple.getTERM()) {
		if (obj instanceof psoa.ruleml.parser.jaxb.Var) {
			result.addLast(convert((psoa.ruleml.parser.jaxb.Var) obj,
					absSynFactory));
		} else if (obj instanceof psoa.ruleml.parser.jaxb.Const) {
			result.addLast(convert((psoa.ruleml.parser.jaxb.Const) obj,
					absSynFactory));
		} else if (obj instanceof psoa.ruleml.parser.jaxb.Expr) {
			result.addLast(convert((psoa.ruleml.parser.jaxb.Expr) obj,
					absSynFactory));
		} else if (obj instanceof psoa.ruleml.parser.jaxb.ExternalTERMType) {
			result.addLast(convert(
					(psoa.ruleml.parser.jaxb.ExternalTERMType) obj,
					absSynFactory));
		} else
			throw new Error("Bad instance of tuple");
	}

	ArrayList<AbstractSyntax.Tuple> res = new ArrayList<AbstractSyntax.Tuple>();
	res.add(absSynFactory.createTuple(result));

	return res;
}

/**
 * 
 * @param member
 *            to be parsed as membership with Object ID as instance of a
 *            class
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create
 * @return Psoa term containing membership
 */
private Psoa convert(Member member, AbstractSyntax absSynFactory) {

	Instance instance = member.getInstance();
	assert instance != null;
	AbstractSyntax.Term inst;

	if (instance.getConst() != null) {
		inst = convert(instance.getConst(), absSynFactory);
	} else if (instance.getVar() != null) {
		inst = convert(instance.getVar(), absSynFactory);
	} else if (instance.getExpr() != null) {
		inst = convert(instance.getExpr(), absSynFactory);
	} else if (instance.getExternal() != null) {
		inst = convert(instance.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Instance");

	psoa.ruleml.parser.jaxb.Class className = member.getClazz();
	assert className != null;
	AbstractSyntax.Term cls;

	if (className.getConst() != null) {
		cls = convert(className.getConst(), absSynFactory);
	} else if (className.getVar() != null) {
		cls = convert(className.getVar(), absSynFactory);
	} else if (className.getExpr() != null) {
		cls = convert(className.getExpr(), absSynFactory);
	} else if (className.getExternal() != null) {
		cls = convert(className.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Class");

	return absSynFactory.createPsoa(inst, cls, null, null);
}

/*******************************************************
 * 
 * @param subclass
 *            to be parsed as Subclass
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create subclass
 * @return Subclass with term sub class and super class
 */
private Subclass convert(psoa.ruleml.parser.jaxb.Subclass subclass,
		AbstractSyntax absSynFactory) {

	Sub sub = subclass.getSub();
	assert sub != null;

	AbstractSyntax.Term subcls;

	if (sub.getVar() != null) {
		subcls = convert(sub.getVar(), absSynFactory);
	} else if (sub.getConst() != null) {
		subcls = convert(sub.getConst(), absSynFactory);
	} else if (sub.getExpr() != null) {
		subcls = convert(sub.getExpr(), absSynFactory);
	} else if (sub.getExternal() != null) {
		subcls = convert(sub.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Sub");

	Super sup = subclass.getSuper();
	assert sup != null;
	AbstractSyntax.Term supcls;

	if (sup.getVar() != null) {
		supcls = convert(sup.getVar(), absSynFactory);
	} else if (sup.getConst() != null) {
		supcls = convert(sup.getConst(), absSynFactory);
	} else if (sup.getExpr() != null) {
		supcls = convert(sup.getExpr(), absSynFactory);
	} else if (sup.getExternal() != null) {
		supcls = convert(sup.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Super");

	return absSynFactory.createSubclass(subcls, supcls);
}

/********************************************
 * 
 * @param const1
 *            to be parsed as Const
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Constant
 * @return short constant or literal constant with type
 */
private Term convert(Const const1, AbstractSyntax absSynFactory) {
	for (java.lang.Object obj : const1.getContent())
		if (obj instanceof String) {

			String str = (String) obj;

			if (str.contains("^^")) {
				String[] temp;
				/* delimiter */
				String delimiter = "\"";
				/*
				 * given string will be split by the argument delimiter
				 * provided.
				 */
				temp = str.split(delimiter);
				/* print substrings */
				// for(int i =0; i < temp.length ; i++)
				// System.out.println("split "+(i+1) +": " +temp[i]);
				String oldString = temp[2];
				// String symspaceStr =
				// oldString.toLowerCase().split("^^")[1];
				String symspaceStr = oldString.substring(2);
				String literalStr = temp[1];

				return absSynFactory.createConst_Literal(literalStr,
						convert(symspaceStr, absSynFactory));
			} else {

				return absSynFactory.createConst_Constshort((String) obj);
			}

		} else
			throw new Error("Bad instance of Const");

	return null;
}

/**
 * 
 * @param symspaceStr
 *            to be parsed as constant literal type
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create literal type
 * @return Symspace as literal type for literal constant
 */
private Symspace convert(String symspaceStr, AbstractSyntax absSynFactory) {

	if (!symspaceStr.isEmpty()) {
		return absSynFactory.createSymspace(symspaceStr);
	} else
		throw new Error("bad instance of Symspace");
}

/**
 * 
 * @param declare
 *            to be parsed as variable declaration
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create variable declaration sequence
 * @return sequence of declaration of variables
 */
private Iterable<Var> convertVars(List<Declare> declare,
		AbstractSyntax absSynFactory) {

	LinkedList<AbstractSyntax.Var> results = new LinkedList<AbstractSyntax.Var>();

	for (Declare var : declare) {
		results.addLast(convert(var.getVar(), absSynFactory));
	}

	return results;
}

/**
 * 
 * @param var
 *            as Variable
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create variable
 * @return variable
 */
private Var convert(psoa.ruleml.parser.jaxb.Var var,
		AbstractSyntax absSynFactory) {

	for (java.lang.Object obj : var.getContent()) {
		if (obj instanceof String) {
			return absSynFactory.createVar((String) obj);
		}
	}

	return absSynFactory.createVar("");
}

/*************************************************
 * 
 * @param equal
 *            to be parsed as Equal atomic formula
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create Equality atomic formula
 * @return Equal atomic formula
 */
private AbstractSyntax.Equal convert(psoa.ruleml.parser.jaxb.Equal equal,
		AbstractSyntax absSynFactory) {

	Left left = equal.getLeft();
	assert left != null;
	AbstractSyntax.Term lhs;

	if (left.getVar() != null) {
		lhs = convert(left.getVar(), absSynFactory);
	} else if (left.getConst() != null) {
		lhs = convert(left.getConst(), absSynFactory);
	} else if (left.getExpr() != null) {
		lhs = convert(left.getExpr(), absSynFactory);
	} else if (left.getExternal() != null) {
		lhs = convert(left.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Left");

	Right right = equal.getRight();
	assert right != null;
	AbstractSyntax.Term rhs;

	if (right.getVar() != null) {
		rhs = convert(right.getVar(), absSynFactory);
	} else if (right.getConst() != null) {
		rhs = convert(right.getConst(), absSynFactory);
	} else if (right.getExpr() != null) {
		rhs = convert(right.getExpr(), absSynFactory);
	} else if (right.getExternal() != null) {
		rhs = convert(right.getExternal(), absSynFactory);
	} else
		throw new Error("Bad instance of Right");

	return absSynFactory.createEqual(lhs, rhs);
}

/**
 * 
 * @param external
 *            to be parsed as External expression
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create external expression
 * @return External atomic expression
 */
private AbstractSyntax.External convert(ExternalTERMType external,
		AbstractSyntax absSynFactory) {

	return absSynFactory.createExternalExpr((Psoa) convert(external
			.getContent().getExpr(), absSynFactory));
}

/**
 * 
 * @param expr
 *            to be parsed as expression
 * @param absSynFactory
 *            factory of abstract syntax objects to be used to create the
 *            parsed objects to create expression
 * @return
 */
private Term convert(Expr expr, AbstractSyntax absSynFactory) {

	if (expr.getMember() != null && expr.getTuple() != null
			&& expr.getSlot() != null) {
		return convert(expr.getMember(), expr.getTuple(), expr.getSlot(),
				absSynFactory);
	} else if (expr.getMember() != null && expr.getTuple() != null) {
		return convert(expr.getMember(), expr.getTuple(), absSynFactory);
	} else if (expr.getMember() != null && expr.getSlot() != null) {
		return convert(expr.getMember(), expr.getSlot(), absSynFactory);
	} else if (expr.getMember() != null) {
		return convert(expr.getMember(), absSynFactory);
	} else
		throw new Error("Bad instance of Expr");
}

private Unmarshaller _unmarshaller;
private Marshaller _marshaller;
}
